package com.library.common.aop;

import com.library.common.config.CheckParamNull;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestBindingException;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

@Aspect
@Component
public class CheckParamNullAspect {

      /**
        * pointcut
        * 定义切点：被@CheckParamNull注解的方法
        */
    @Pointcut("execution( * * (..,@com.library.common.config.CheckParamNull (*),..))")
    public void pointcut() {
                 // do nothing
    }

     /**
       * around
       * 环绕增强方法，可以控制切点前后的代码执行。
       */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
                 MethodSignature signature = ((MethodSignature) point.getSignature());

         //得到拦截的方法
         Method method = signature.getMethod();
         //获取方法参数注解，返回二维数组是因为某些参数可能存在多个注解
         Annotation[][] parameterAnnotations = method.getParameterAnnotations();
         if (parameterAnnotations == null || parameterAnnotations.length == 0) {
                 return point.proceed();
             }

         //获取方法参数名
         String[] paramNames = signature.getParameterNames();
         //获取参数值
         Object[] paranValues = point.getArgs();
         //获取方法参数类型
        //        Class<?>[] parameterTypes = method.getParameterTypes();
         for (int i = 0; i < parameterAnnotations.length; i++) {
                 for (int j = 0; j < parameterAnnotations[i].length; j++) {
                         //如果该参数前面的注解是CheckParamNull的实例，并且notNull()=true,则进行非空校验
                         if (parameterAnnotations[i][j] != null && parameterAnnotations[i][j] instanceof CheckParamNull) {
                                 paramIsNull(paramNames[i], paranValues[i], ((CheckParamNull) parameterAnnotations[i][j]));
                                 break;
                         }
                 }
         }
         return point.proceed();
    }

     /**
       * 参数非空校验，如果参数为空，则抛出ServletRequestBindingException异常
       * @param paramName
       * @param value
       * @param checkParamNull
       */
    private void paramIsNull(String paramName, Object value, CheckParamNull checkParamNull) throws ServletRequestBindingException {
     if (checkParamNull.notNull() && value == null) {
             throw new ServletRequestBindingException("Required String parameter '"+paramName+"' is not present");
         }else if(checkParamNull.notBlank() && StringUtils.isBlank(value.toString().trim())){
             throw new ServletRequestBindingException("Required String parameter '"+paramName+"' is must not blank");
         }

    }
}